package com.gitee.qdbp.general.common.biz.site.service;

import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.jdbc.paging.Paging;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.system.model.IAccount;
import com.gitee.qdbp.general.common.api.site.basic.IContentPublishBasic;
import com.gitee.qdbp.general.common.api.site.model.content.ContentPublishBean;
import com.gitee.qdbp.general.common.api.site.model.content.ContentPublishUpdate;
import com.gitee.qdbp.general.common.api.site.model.content.ContentPublishWhere;
import com.gitee.qdbp.general.common.api.site.service.IContentPublishExecutor;
import com.gitee.qdbp.general.common.error.GeneralErrorCode;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 内容发布业务处理类
 *
 * @author zhh
 * @version 171012
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public class ContentPublishExecutor implements IContentPublishExecutor {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(ContentPublishExecutor.class);

    /** 内容发布DAO **/
    @Autowired
    private IContentPublishBasic contentPublishBasic;

    @Override
    public void create(ContentPublishBean model, IAccount me) throws ServiceException {
        String msg = "Failed to create ContentPublish. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        // 判断CategoryCode不能为空
        String categoryCode = model.getCategoryCode();
        if (VerifyTools.isBlank(categoryCode)) {
            log.error(msg + "params is null: CategoryCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        // 判断PlaceCode不能为空
        String placeCode = model.getPlaceCode();
        if (VerifyTools.isBlank(placeCode)) {
            log.error(msg + "params is null: PlaceCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        if (VerifyTools.isBlank(model.getSortIndex())) { // 未指定, 添加到最后
            ContentPublishWhere where = new ContentPublishWhere();
            where.setTenantCode(model.getTenantCode());
            where.setCategoryCode(categoryCode);
            where.setPlaceCode(placeCode);
            OrderPaging p = OrderPaging.of(new Paging(1, 1), "sortIndex desc"); // 按sortIndex降序取第1条
            PageList<ContentPublishBean> temp = contentPublishBasic.list(where, p);
            int sortIndex = 1;
            if (VerifyTools.isNotBlank(temp)) {
                ContentPublishBean max = temp.get(0);
                sortIndex = Math.max(VerifyTools.nvl(max.getSortIndex(), 0) + 1, temp.getTotal());
            }
            model.setSortIndex(sortIndex);
        } else { // 将现在记录向后移, 为新记录腾出位置
            int sortIndex = model.getSortIndex();

            ContentPublishUpdate ud = new ContentPublishUpdate();
            ud.setSortIndexAdd(1);
            ContentPublishWhere where = ud.getWhere(true);
            where.setTenantCode(model.getTenantCode());
            where.setCategoryCode(categoryCode);
            where.setPlaceCode(placeCode);
            where.setSortIndexMin(sortIndex);
            contentPublishBasic.update(ud, false);
        }

        // 向gn_content_publish表插入记录
        contentPublishBasic.create(model);

    }

    @Override
    public void update(ContentPublishUpdate model, IAccount me) throws ServiceException {
        String msg = "Failed to update ContentPublish. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(model)) {
            log.error(msg + "params is null: model");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        String id = model.getId();
        if (VerifyTools.isBlank(id) && model.getWhere() != null) {
            id = model.getWhere().getId();
        }
        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        // 原始记录检查
        ContentPublishBean older = contentPublishBasic.findById(id);
        if (older == null) {
            log.error(msg + "record is not found. id=" + id);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }

        ContentPublishUpdate newer = createChangedModel(model, older);

        if (newer != null) {
            if (VerifyTools.isNotBlank(newer.getSortIndex())) { // 有修改排序号
                doUpdateIndex(older, newer.getSortIndex(), false, me);
            }

            // 更新gn_content_publish表的记录
            contentPublishBasic.update(newer, false);
        }

    }

    @Override
    public void delete(String categoryCode, String id, IAccount me) throws ServiceException {
        String msg = "Failed to delete ContentPublish. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(categoryCode)) {
            log.error(msg + "params is null: categoryCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(id)) {
            log.error(msg + "params is null: id");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        ContentPublishWhere where = new ContentPublishWhere();
        where.setCategoryCode(categoryCode);
        where.setId(id);
        // 删除gn_content_publish表的记录
        contentPublishBasic.delete(where, false);

    }

    @Override
    public void delete(String categoryCode, List<String> ids, IAccount me) throws ServiceException {
        String msg = "Failed to delete ContentPublish. ";

        if (VerifyTools.isBlank(me)) {
            log.error(msg + "params is null: me");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(categoryCode)) {
            log.error(msg + "params is null: categoryCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        if (VerifyTools.isBlank(ids)) {
            log.error(msg + "params is null: ids");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        ContentPublishWhere where = new ContentPublishWhere();
        where.setCategoryCode(categoryCode);
        where.setIds(ids);
        // 删除gn_content_publish表的记录
        contentPublishBasic.delete(where, false);

    }

    @Override
    public void swapIndex(String categoryCode, String oneId, String twoId, IAccount me) throws ServiceException {
        String msg = "Failed to swap ContentPublish. ";

        String tenantCode = me.getTenantCode();
        ContentPublishBean one = findByIdThrowOnNotExists(oneId, tenantCode, msg);
        ContentPublishBean two = findByIdThrowOnNotExists(twoId, tenantCode, msg);

        if (!one.getCategoryCode().equals(categoryCode)) {
            log.error(msg + "CategoryCode must be same: {}.categoryCode != {}", oneId, categoryCode);
            throw new ServiceException(ResultCode.ACCESS_DENIED);
        }
        if (!two.getCategoryCode().equals(categoryCode)) {
            log.error(msg + "CategoryCode must be same: {}.categoryCode != {}", twoId, categoryCode);
            throw new ServiceException(ResultCode.ACCESS_DENIED);
        }
        if (!one.getPlaceCode().equals(two.getPlaceCode())) {
            log.error(msg + "PlaceCode must be same: {}.placeCode != {}.placeCode", twoId, twoId);
            throw new ServiceException(GeneralErrorCode.SORT_INDEX_SWAP_PARENT_NOT_SAME);
        }
        
        String placeCode = one.getPlaceCode();
        if (one.getSortIndex().equals(two.getSortIndex())) {
            int index = one.getSortIndex();
            { // 大于等于当前序号的全部加1
                ContentPublishUpdate ud = new ContentPublishUpdate();
                ud.setSortIndexAdd(1);
                ContentPublishWhere where = ud.getWhere(true);
                where.setCategoryCode(categoryCode);
                where.setPlaceCode(placeCode);
                where.setSortIndexMin(index);
                contentPublishBasic.update(ud, false);
            }
            { // one再改成之前的序号
                ContentPublishUpdate ud = new ContentPublishUpdate();
                ud.setSortIndex(index);
                ContentPublishWhere where = ud.getWhere(true);
                where.setCategoryCode(categoryCode);
                where.setPlaceCode(placeCode);
                where.setId(oneId);
                contentPublishBasic.update(ud, false);
            }
        } else {
            { // one的序号改成two的序号
                ContentPublishUpdate ud = new ContentPublishUpdate();
                ud.setSortIndex(two.getSortIndex());
                ContentPublishWhere where = ud.getWhere(true);
                where.setId(oneId);
                where.setCategoryCode(categoryCode);
                where.setPlaceCode(placeCode);
                contentPublishBasic.update(ud, false);
            }
            { // two的序号改成one的序号
                ContentPublishUpdate ud = new ContentPublishUpdate();
                ud.setSortIndex(one.getSortIndex());
                ContentPublishWhere where = ud.getWhere(true);
                where.setId(twoId);
                where.setCategoryCode(categoryCode);
                where.setPlaceCode(placeCode);
                where.setSortIndex(two.getSortIndex());
                contentPublishBasic.update(ud, false);
            }
        }

    }

    private void doUpdateIndex(ContentPublishBean older, int sortIndex, boolean moveSelf, IAccount me)
            throws ServiceException {

        String categoryCode = older.getCategoryCode();
        String placeCode = older.getPlaceCode();
        if (sortIndex > older.getSortIndex()) { // 向后移
            // 先将中间的记录向前移
            // 如: 原先是3, 想移动到6, 则先将456向前移, 变成345, 再将原先的3变成6
            ContentPublishUpdate ud = new ContentPublishUpdate();
            ud.setSortIndexAdd(-1);
            ContentPublishWhere where = ud.getWhere(true);
            where.setSortIndexMin(older.getSortIndex() + 1);
            where.setSortIndexMax(sortIndex);
            where.setCategoryCode(categoryCode);
            where.setPlaceCode(placeCode);
            where.setTenantCode(me.getTenantCode());
            contentPublishBasic.update(ud, false);
        } else { // 向前移
            // 先将中间的记录向后移
            // 如: 原先是6, 想移动到3, 则先将345向后移, 变成456, 再将原先的6变成3
            ContentPublishUpdate ud = new ContentPublishUpdate();
            ud.setSortIndexAdd(+1);
            ContentPublishWhere where = ud.getWhere(true);
            where.setSortIndexMin(sortIndex);
            where.setSortIndexMax(older.getSortIndex() - 1);
            where.setCategoryCode(categoryCode);
            where.setPlaceCode(placeCode);
            where.setTenantCode(me.getTenantCode());
            contentPublishBasic.update(ud, false);
        }
        if (moveSelf) { // 再将自已移动到指定位置
            ContentPublishUpdate ud = new ContentPublishUpdate();
            ud.setSortIndex(sortIndex);
            ContentPublishWhere where = ud.getWhere(true);
            where.setId(older.getId());
            where.setCategoryCode(categoryCode);
            where.setPlaceCode(placeCode);
            where.setTenantCode(me.getTenantCode());
            contentPublishBasic.update(ud, true);
        }
    }

    /** 检查数据是否存在, 不存在则报错 **/
    private ContentPublishBean findByIdThrowOnNotExists(String id, String tenantCode, String msg)
            throws ServiceException {

        ContentPublishWhere where = new ContentPublishWhere();
        where.setId(id);
        where.setTenantCode(tenantCode);

        ContentPublishBean bean = contentPublishBasic.find(where);

        if (bean == null) {
            log.warn(msg + "ContentPublish not found, id=" + id);
            throw new ServiceException(ResultCode.RECORD_NOT_EXIST);
        }
        return bean;
    }

    /**
     * 创建一个新的对象, 只包含改动过的字段
     *
     * @author zhh
     * @param model 目标对象(一般是参数传入的)
     * @param older 源对象(一般是从数据库查询得到的)
     * @return 只包含有更新的字段对象
     */
    private ContentPublishUpdate createChangedModel(ContentPublishUpdate model, ContentPublishBean older) {
        ContentPublishUpdate newer = new ContentPublishUpdate();
        newer.setWhere(model.getWhere());

        boolean changed = false;
        newer.setId(model.getId()); // 主键

        // if (VerifyTools.isChanged(model.getTenantCode(), older.getTenantCode())) {
        //     changed = true;
        //     newer.setTenantCode(model.getTenantCode()); // 租户编号
        // }
        // if (VerifyTools.isChanged(model.getCategoryCode(), older.getCategoryCode())) {
        //     changed = true;
        //     newer.setCategoryCode(model.getCategoryCode()); // 分类编号
        // }
        if (VerifyTools.isChanged(model.getPlaceCode(), older.getPlaceCode())) {
            changed = true;
            newer.setPlaceCode(model.getPlaceCode()); // 位置编号
        }
        if (VerifyTools.isChanged(model.getContentCode(), older.getContentCode())) {
            changed = true;
            newer.setContentCode(model.getContentCode()); // 内容编号
        }
        if (VerifyTools.isChanged(model.getContentTitle(), older.getContentTitle())) {
            changed = true;
            newer.setContentTitle(model.getContentTitle()); // 标题
        }
        if (VerifyTools.isChanged(model.getContentValue(), older.getContentValue())) {
            changed = true;
            newer.setContentValue(model.getContentValue()); // 内容
        }
        if (VerifyTools.isChanged(model.getContentDesc(), older.getContentDesc())) {
            changed = true;
            newer.setContentDesc(model.getContentDesc()); // 描述
        }
        if (VerifyTools.isChanged(model.getSortIndex(), older.getSortIndex())) {
            changed = true;
            newer.setSortIndex(model.getSortIndex()); // 排序值(越小越靠前)
        }
        if (VerifyTools.isChanged(model.getOptions(), older.getOptions())) {
            changed = true;
            newer.setOptions(model.getOptions()); // 选项
        }
        // if (VerifyTools.isChanged(model.getCreateTime(), older.getCreateTime())) {
        //     changed = true;
        //     newer.setCreateTime(model.getCreateTime()); // 创建时间
        // }
        if (VerifyTools.isChanged(model.getActiveTime(), older.getActiveTime())) {
            changed = true;
            newer.setActiveTime(model.getActiveTime()); // 激活时间
        }
        if (VerifyTools.isChanged(model.getExpireTime(), older.getExpireTime())) {
            changed = true;
            newer.setExpireTime(model.getExpireTime()); // 过期时间
        }
        // if (VerifyTools.isChanged(model.getUsingState(), older.getUsingState())) {
        //     changed = true;
        //     newer.setUsingState(model.getUsingState()); // 启用状态(1.正常|2.未启用)
        // }
        // if (VerifyTools.isChanged(model.getDataState(), older.getDataState())) {
        //     changed = true;
        //     newer.setDataState(model.getDataState()); // 数据状态:0为正常|其他为删除
        // }
        // if (Boolean.TRUE.equals(model.isTenantCodeToNull())) {
        //     changed = true;
        //     newer.setTenantCodeToNull(true); // 租户编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isCategoryCodeToNull())) {
        //     changed = true;
        //     newer.setCategoryCodeToNull(true); // 分类编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isPlaceCodeToNull())) {
        //     changed = true;
        //     newer.setPlaceCodeToNull(true); // 位置编号更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isContentTitleToNull())) {
        //     changed = true;
        //     newer.setContentTitleToNull(true); // 标题更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isContentValueToNull())) {
        //     changed = true;
        //     newer.setContentValueToNull(true); // 内容更新为空值
        // }
        if (Boolean.TRUE.equals(model.isContentDescToNull())) {
            changed = true;
            newer.setContentDescToNull(true); // 描述更新为空值
        }
        // if (Boolean.TRUE.equals(model.isSortIndexToNull())) {
        //     changed = true;
        //     newer.setSortIndexToNull(true); // 排序值(越小越靠前)更新为空值
        // }
        // if (VerifyTools.isNotBlank(model.getSortIndexAdd()) && model.getSortIndexAdd() != 0) {
        //     changed = true;
        //     newer.setSortIndexAdd(model.getSortIndex()); // 排序值(越小越靠前)的增加值
        // }
        // if (Boolean.TRUE.equals(model.isOptionsToNull())) {
        //     changed = true;
        //     newer.setOptionsToNull(true); // 选项更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isActiveTimeToNull())) {
        //     changed = true;
        //     newer.setActiveTimeToNull(true); // 激活时间更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isActiveTimeToCurrent())) {
        //     changed = true;
        //     newer.setActiveTimeToCurrent(true); // 激活时间更新为数据库当前时间
        // }
        // if (VerifyTools.isNotBlank(model.getActiveTimeAdd()) && model.getActiveTimeAdd() != 0) {
        //     changed = true;
        //     newer.setActiveTimeAdd(model.getActiveTime()); // 激活时间的增加值
        // }
        // if (Boolean.TRUE.equals(model.isExpireTimeToNull())) {
        //     changed = true;
        //     newer.setExpireTimeToNull(true); // 过期时间更新为空值
        // }
        // if (Boolean.TRUE.equals(model.isExpireTimeToCurrent())) {
        //     changed = true;
        //     newer.setExpireTimeToCurrent(true); // 过期时间更新为数据库当前时间
        // }
        // if (VerifyTools.isNotBlank(model.getExpireTimeAdd()) && model.getExpireTimeAdd() != 0) {
        //     changed = true;
        //     newer.setExpireTimeAdd(model.getExpireTime()); // 过期时间的增加值
        // }
        // if (Boolean.TRUE.equals(model.isUsingStateToNull())) {
        //     changed = true;
        //     newer.setUsingStateToNull(true); // 启用状态(1.正常|2.未启用)更新为空值
        // }
        return changed ? newer : null;

    }

}
